package com.eshipenet.shipnet.edgechannelbuilder

import scala.util.Try

sealed trait EdgeBoxAction {
  def genChannelAction: List[EdgeChannelAction]
}
case class EdgeBoxInsert(after: EdgeBox) extends EdgeBoxAction {
  override def genChannelAction: List[EdgeChannelAction] =
    after.globalChannels().map(ch => EdgeChannelInsert(ch)).toList
}
case class EdgeBoxUpdate(before: EdgeBox, after: EdgeBox) extends EdgeBoxAction {
  override def genChannelAction: List[EdgeChannelAction] = {
    val beforeChs     = before.globalChannels().map(ch => ch.id -> ch).toMap
    val afterChs      = after.globalChannels().map(ch => ch.id -> ch).toMap
    val beforeIds     = beforeChs.keys.toSet
    val afterIds      = afterChs.keys.toSet
    val deleted       = beforeIds -- afterIds
    val created       = afterIds -- beforeIds
    val intersect     = beforeIds.intersect(afterIds)
    val deleteActions = deleted.map(beforeChs(_)).map(EdgeChannelDelete).toList
    val createActions = created.map(afterChs(_)).map(EdgeChannelInsert).toList
    val notSame       = (id: String) => beforeChs(id) != afterChs(id)
    val updateActions = intersect
      .filter(notSame)
      .map(id => beforeChs(id) -> afterChs(id))
      .map(p => EdgeChannelUpdate(p._1, p._2))
      .toList
    deleteActions ++ createActions ++ updateActions
  }
}
case class EdgeBoxDelete(before: EdgeBox) extends EdgeBoxAction {
  override def genChannelAction: List[EdgeChannelAction] =
    before.globalChannels().map(EdgeChannelDelete).toList
}

object EdgeBoxAction {

  def apply(act: DebeziumParser.Action): Try[EdgeBoxAction] = act match {
    case DebeziumParser.Insert(after) =>
      Try {
        val box = after.as[EdgeBox]
        EdgeBoxInsert(box)
      }
    case DebeziumParser.Update(before, after) =>
      Try {
        val boxBefore = before.as[EdgeBox]
        val boxAfter  = after.as[EdgeBox]
        EdgeBoxUpdate(boxBefore, boxAfter)
      }
    case DebeziumParser.Delete(before) =>
      Try {
        val box = before.as[EdgeBox]
        EdgeBoxDelete(box)
      }
  }

}
